package com.internetCafes.spms.web.customer.bizservice.impl.customer;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.internetCafes.spms.common.utils.ExcelImportUtil;
import com.internetCafes.spms.common.utils.ShiroUtils;
import com.internetCafes.spms.common.utils.entity.page.PageItemDTO;
import com.internetCafes.spms.common.utils.entity.page.PageItemUtil;
import com.internetCafes.spms.common.utils.entity.page.PageItemVO;
import com.internetCafes.spms.core.exception.RRException;
import com.internetCafes.spms.core.exception.RRExceptionCodeEnum;
import com.internetCafes.spms.core.utils.IdWorker;
import com.internetCafes.spms.web.customer.bizservice.customer.IEntCustomerCooperationBizService;
import com.internetCafes.spms.web.customer.bizservice.customer.IEntCustomerFlowBizService;
import com.internetCafes.spms.web.customer.common.cont.CommonConst;
import com.internetCafes.spms.web.customer.common.cont.CustomerConst;
import com.internetCafes.spms.web.customer.entity.customer.Customer;
import com.internetCafes.spms.web.customer.entity.customer.CustomerCooperation;
import com.internetCafes.spms.web.customer.entity.customer.CustomerCooperationConsume;
import com.internetCafes.spms.web.customer.entity.customer.CustomerCooperationDetail;
import com.internetCafes.spms.web.customer.model.ExcelImportResultRes;
import com.internetCafes.spms.web.customer.model.customer.cooperation.*;
import com.internetCafes.spms.web.customer.service.customer.ICustomerCooperationConsumeService;
import com.internetCafes.spms.web.customer.service.customer.ICustomerCooperationDetailService;
import com.internetCafes.spms.web.customer.service.customer.ICustomerCooperationService;
import com.internetCafes.spms.web.customer.service.customer.ICustomerService;
import com.sms.common.util.hutool.core.bean.BeanUtil;
import com.sms.common.util.hutool.core.collection.CollectionUtil;
import com.sms.common.util.hutool.core.date.DatePattern;
import com.sms.common.util.hutool.core.date.DateTime;
import com.sms.common.util.hutool.core.date.DateUtil;
import com.sms.common.util.hutool.core.util.ObjectUtil;
import com.sms.common.util.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.entity.ImportSheetParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EntCustomerCooperationBizServiceImpl implements IEntCustomerCooperationBizService {


    @Autowired
    private ICustomerCooperationService cooperationService;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private IEntCustomerFlowBizService flowBizService;
    @Autowired
    private ICustomerCooperationDetailService cooperationDetailService;
    @Autowired
    private ICustomerCooperationConsumeService consumeService;

    @Value("${system.upload.others}")
    private String othersPath;

    /**
     * 合作记录excel表头
     */
    private final String[] EXCEL_HEADER = new String[]{"合作简述", "类型", "进款金额", "业绩金额", "进款时间", "明细"};

    @Override
    public List<CustomerConsumeRes> consumeList(Long cooperationId) {
        return consumeService.list(
                        new LambdaQueryWrapper<CustomerCooperationConsume>()
                                .eq(CustomerCooperationConsume::getCooperationId, cooperationId)
                                .orderByDesc(CustomerCooperationConsume::getCreateTime))
                .stream()
                .map(po -> {
                    CustomerConsumeRes res = new CustomerConsumeRes();
                    BeanUtil.copyProperties(po, res);
                    res.setLogTime(DateUtil.format(po.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
                    return res;
                }).collect(Collectors.toList());
    }

    @Override
    public ExcelImportResultRes batchSave(CooperationSaveBatchReq req) {
        if (CollectionUtil.isEmpty(req.getCooperationList()) || ObjectUtil.isNull(req.getCustomerId())) {
            throw new RRException(RRExceptionCodeEnum.PARAM_ERROR);
        }

        int index = 1;

        List<CustomerCooperation> cooperationBatchDo = new ArrayList<>();

        ExcelImportResultRes res = new ExcelImportResultRes();
        for (CooperationImportExcel cooperation : req.getCooperationList()) {
            if (StrUtil.isBlank(cooperation.getDescription()) || StrUtil.isBlank(cooperation.getIncome())
                    || StrUtil.isBlank(cooperation.getIncomeDate())) {
                res.getResultInfoList().add(res.new resultInfo(index, cooperation.getDescription(), CommonConst.FlagEnum.NOT.getId(), RRExceptionCodeEnum.PARAM_ERROR.getMessage()));
                continue;
            }
            CustomerCooperation cooperationDo = new CustomerCooperation();
            BeanUtil.copyProperties(cooperation, cooperationDo);

            Integer typeId = CustomerConst.CooperationType.getIdByType(cooperation.getType());
            if (ObjectUtil.isNull(typeId)) {
                res.getResultInfoList().add(res.new resultInfo(index, cooperation.getDescription(), CommonConst.FlagEnum.NOT.getId(), RRExceptionCodeEnum.CUSTOMER_COOPERATION_TYPE_ERROR.getMessage()));
                continue;
            }
            cooperationDo.setTypeId(typeId);

            try {
                DateTime dateTime = DateUtil.parse(cooperation.getIncomeDate(), DatePattern.NORM_DATE_PATTERN);
                cooperationDo.setIncomeDate(dateTime);
            } catch (Exception e) {
                res.getResultInfoList().add(res.new resultInfo(index, cooperation.getDescription(), CommonConst.FlagEnum.NOT.getId(), RRExceptionCodeEnum.DATE_FORMAT_ERROR.getMessage()));
                continue;
            }
            try {
                BigDecimal income = new BigDecimal(cooperation.getIncome());
                cooperationDo.setIncome(income);
                BigDecimal perfor = new BigDecimal(cooperation.getPerfor());
                cooperationDo.setPerfor(perfor);
            } catch (Exception e) {
                res.getResultInfoList().add(res.new resultInfo(index, cooperation.getDescription(), CommonConst.FlagEnum.NOT.getId(), RRExceptionCodeEnum.DATE_FORMAT_ERROR.getMessage()));
                continue;
            }
            cooperationBatchDo.add(cooperationDo);
        }

        cooperationService.saveBatch(cooperationBatchDo);

        return res.setFailAmount(res.getResultInfoList().size())
                .setSuccessAmount(cooperationBatchDo.size());
    }

    @Override
    public List<CooperationImportExcel> cooperationImportExcel(MultipartFile file) {
        if (file.isEmpty()) {
            throw new RRException(RRExceptionCodeEnum.DATA_IS_NULL);
        }

        IdWorker id = new IdWorker(2);
        String fileType = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
        File videoFilePath = new File(othersPath);
        if (!videoFilePath.exists()) {
            videoFilePath.mkdirs();
        }
        if (fileType.toUpperCase().endsWith("XLS") || fileType.toUpperCase().endsWith("XLSX")) {
            String filePath = othersPath + File.separator + id.nextId() + fileType;

            try {
                file.transferTo(new File(filePath));
            } catch (IOException e) {
                e.printStackTrace();
            }

            Map<String, ImportSheetParams> sheetClassParamsMap = new HashMap<>();
            Map<String, Object> excel2Map;
            sheetClassParamsMap.put("Sheet1", new ImportSheetParams("cooperationImportExcel", 1, 1,
                    EXCEL_HEADER,
                    CooperationImportExcel.class));
            try {
                excel2Map = ExcelImportUtil.importExcel2Map(new File(filePath), sheetClassParamsMap, null);
            } catch (Exception e) {
                throw new RRException(RRExceptionCodeEnum.DATA_IS_NULL);
            }
            return (List<CooperationImportExcel>) excel2Map.get("Sheet1");

        } else {
            throw new RRException(RRExceptionCodeEnum.FILE_FORMAT_ERROR);
        }
    }

    @Override
    public List<CooperationExcel> cooperationExcel(CooperationExcelReq req) {
        LambdaQueryWrapper<CustomerCooperation> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isBlank(req.getCreateByName())) {
            queryWrapper.like(CustomerCooperation::getCreateByName, req.getCreateByName());
        }
        if (ObjectUtil.isNotNull(req.getCustomerId())) {
            queryWrapper.eq(CustomerCooperation::getCustomerId, req.getCustomerId());
        }
        queryWrapper.orderByDesc(CustomerCooperation::getCreateTime);
        List<CustomerCooperation> listPo = cooperationService.list(queryWrapper);
        return listPo.stream().map(
                        po -> {
                            CooperationExcel res = new CooperationExcel();
                            BeanUtil.copyProperties(po, res);
                            res.setIncome(po.getIncome().toString())
                                    .setIncomeDate(DateUtil.format(po.getIncomeDate(), DatePattern.NORM_DATE_PATTERN))
                                    .setCreateTime(DateUtil.format(po.getCreateTime(), DatePattern.NORM_DATE_PATTERN))
                                    .setPerfor(po.getPerfor().toString())
                                    .setType(CustomerConst.CooperationType.getTypeById(po.getTypeId()));
                            return res;
                        })
                .collect(Collectors.toList());
    }

    @Override
    public PageItemVO<CustomerCooperationPagingRes> paging(PageItemDTO<CustomerCooperationPagingReq> req) {
        Page<CustomerCooperation> pagingDo = new Page<>(req.getPageNum(), req.getPageSize());
        CustomerCooperationPagingReq conditions = req.getConditions();
        CustomerCooperationPagingDo cooperationPagingDo = new CustomerCooperationPagingDo();
        if (ObjectUtil.isNotNull(conditions)) {
            BeanUtil.copyProperties(conditions, cooperationPagingDo);
        }
        Page<CustomerCooperationPagingPo> pagingPo = cooperationService.paging(pagingDo, cooperationPagingDo);
        PageItemVO<CustomerCooperationPagingRes> pagingRes = PageItemUtil.toPageItemVO(pagingPo, new PageItemVO<>());

        Map<Long, List<CooperationDetailRes>> detailListByCooperationId = new HashMap<>();
        Map<Long, List<CustomerConsumeRes>> consumeListGroupByCooperationId = new HashMap<>();
        if (CollectionUtil.isNotEmpty(pagingPo.getRecords())) {
            List<Long> cooperationIdList = pagingPo.getRecords().stream().map(CustomerCooperationPagingPo::getId).collect(Collectors.toList());
            // 获取合作记录明细
            List<CustomerCooperationDetail> detailList = cooperationDetailService.list(new LambdaQueryWrapper<CustomerCooperationDetail>().in(CustomerCooperationDetail::getCooperationId, cooperationIdList));

            detailListByCooperationId = detailList.stream()
                    .map(detail -> {
                        CooperationDetailRes detailRes = new CooperationDetailRes();
                        BeanUtil.copyProperties(detail, detailRes);
                        return detailRes;
                    })
                    .collect(Collectors.groupingBy(CooperationDetailRes::getCooperationId));

            consumeListGroupByCooperationId = consumeService.list(
                            new LambdaQueryWrapper<CustomerCooperationConsume>().in(CustomerCooperationConsume::getCooperationId, cooperationIdList)
                                    .orderByDesc(CustomerCooperationConsume::getCreateTime))
                    .stream()
                    .map(po -> {
                        CustomerConsumeRes res = new CustomerConsumeRes();
                        BeanUtil.copyProperties(po, res);
                        res.setLogTime(DateUtil.format(po.getCreateTime(), DatePattern.NORM_DATE_PATTERN));
                        return res;
                    }).collect(Collectors.groupingBy(CustomerConsumeRes::getCooperationId));
        }

        Map<Long, List<CooperationDetailRes>> finalDetailListByCooperationId = detailListByCooperationId;
        Map<Long, List<CustomerConsumeRes>> finalConsumeListGroupByCooperationId = consumeListGroupByCooperationId;
        pagingRes.setRecords(
                pagingPo.getRecords()
                        .stream()
                        .map(po -> {
                            CustomerCooperationPagingRes res = new CustomerCooperationPagingRes();
                            BeanUtil.copyProperties(po, res);
                            res.setIncomeDate(DateUtil.format(po.getIncomeDate(), DatePattern.NORM_DATE_PATTERN))
                                    .setCreateTime(DateUtil.format(po.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN));
                            if (finalDetailListByCooperationId.containsKey(po.getId())) {
                                res.setIncomeDetailList(finalDetailListByCooperationId.get(po.getId()));
                            }
                            if (finalConsumeListGroupByCooperationId.containsKey(po.getId())) {
                                res.setConsumeList(finalConsumeListGroupByCooperationId.get(po.getId()));
                            }
                            return res;
                        })
                        .collect(Collectors.toList()));
        return pagingRes;
    }

    @Override
    public boolean deleteByIdList(List<Long> idList) {
        cooperationService.removeByIds(idList);
        cooperationDetailService.remove(new LambdaQueryWrapper<CustomerCooperationDetail>()
                .in(CustomerCooperationDetail::getCooperationId, idList));
        return true;
    }

    @Override
    public boolean update(CustomerCooperationUpdateReq req) {
        // 必要字段判断
        if (ObjectUtil.isNull(req.getId()) || ObjectUtil.isNull(req.getIncome()) || StrUtil.isBlank(req.getIncomeDate())
                || ObjectUtil.isNull(req.getPerfor()) || CollectionUtil.isEmpty(req.getIncomeDetailList())
                || ((req.getIncome().compareTo(BigDecimal.ZERO) > 0 &&
                (StrUtil.isBlank(req.getIncomeAccount()) || ObjectUtil.isNull(req.getIncomeAccountId()))))) {
            throw new RRException(RRExceptionCodeEnum.PARAM_ERROR);
        }

        // 原有数据
        CustomerCooperation cooperationPo = cooperationService.getById(req.getId());

        if (ObjectUtil.isNull(cooperationPo)) {
            throw new RRException(RRExceptionCodeEnum.DATA_NOT_EXIST);
        }

        CustomerCooperation cooperationDo = new CustomerCooperation();
        BeanUtil.copyProperties(req, cooperationDo);
        DateTime incomeDate = DateUtil.parse(req.getIncomeDate(), DatePattern.NORM_DATE_PATTERN);
        cooperationDo.setIncomeDate(incomeDate);
        // moneySignFilter(cooperationDo);
        cooperationDetailService.saveCooperationDetailList(req.getIncomeDetailList(), req.getId());

        updateDealFlagOfCustomer(incomeDate, req.getCustomerId());

        if (ObjectUtil.isNotNull(cooperationDo.getConsume()) && cooperationPo.getConsume().compareTo(cooperationDo.getConsume()) != 0) {
            CustomerCooperationConsume consumeDo = new CustomerCooperationConsume();
            consumeDo.setCooperationId(cooperationDo.getId())
                    .setConsume(cooperationDo.getConsume().subtract(cooperationPo.getConsume()))
                    .setOriginalConsume(cooperationPo.getConsume())
                    .setFinalConsume(cooperationDo.getConsume());
            consumeService.save(consumeDo);
        }

        return cooperationService.updateById(cooperationDo);
    }

    @Override
    public boolean save(CustomerCooperationSaveReq req) {
        // 必要字段判断
        if (ObjectUtil.isNull(req.getCustomerId()) || StrUtil.isBlank(req.getIncomeDate()) || ObjectUtil.isNull(req.getPerfor())
                || CollectionUtil.isEmpty(req.getIncomeDetailList())
                || ((req.getIncome().compareTo(BigDecimal.ZERO) > 0 &&
                (StrUtil.isBlank(req.getIncomeAccount()) || ObjectUtil.isNull(req.getIncomeAccountId()))))) {
            throw new RRException(RRExceptionCodeEnum.PARAM_ERROR);
        }

        // 获取原有数据
        Customer customerPo = customerService.getById(req.getCustomerId());
        if (ObjectUtil.isNull(customerPo)) {
            throw new RRException(RRExceptionCodeEnum.DATA_NOT_EXIST);
        }

        // 查看当前用户是否为跟进人
        if (CustomerConst.TypeEnum.DEAL.getId().equals(customerPo.getTypeId()) && !customerPo.getFollowUserId().equals(ShiroUtils.getUserId())) {
            throw new RRException(RRExceptionCodeEnum.NO_AUTHORITY);
        }

        // 添加合作记录
        CustomerCooperation cooperationDo = new CustomerCooperation();
        BeanUtil.copyProperties(req, cooperationDo);
        DateTime incomeDate = DateUtil.parse(req.getIncomeDate(), DatePattern.NORM_DATE_PATTERN);
        cooperationDo.setIncomeDate(incomeDate);
        boolean result = cooperationService.save(cooperationDo);

        cooperationDetailService.saveCooperationDetailList(req.getIncomeDetailList(), cooperationDo.getId());

        if (result && !CustomerConst.TypeEnum.DEAL.getId().equals(customerPo.getTypeId())) {
            flowBizService.deal(customerPo);
        }

        updateDealFlagOfCustomer(incomeDate, req.getCustomerId());

        if (ObjectUtil.isNotNull(cooperationDo.getConsume()) && BigDecimal.ZERO.compareTo(cooperationDo.getConsume()) == -1) {
            CustomerCooperationConsume consumeDo = new CustomerCooperationConsume();
            consumeDo.setCooperationId(cooperationDo.getId())
                    .setConsume(cooperationDo.getConsume())
                    .setOriginalConsume(BigDecimal.ZERO)
                    .setFinalConsume(cooperationDo.getConsume());
            consumeService.save(consumeDo);
        }

        return result;
    }

    /**
     * // 修改客户成交之后根据年限判断成交标签
     * 判断成交记录是否是今年的
     *
     * @param incomeDate 收入时间
     * @param customerId 客户id
     */
    public void updateDealFlagOfCustomer(DateTime incomeDate, Long customerId) {

        DateTime now = DateTime.now();
        int incomeYear = incomeDate.year();
        int nowYear = now.year();
        if (incomeYear == nowYear) {
            customerService.updateById(new Customer().setId(customerId).setThisYearDealFlag(CommonConst.FlagEnum.IS.getId()));
        }
        if ((nowYear - incomeYear) == 1) {
            customerService.updateById(new Customer().setId(customerId).setLastYearDealFlag(CommonConst.FlagEnum.IS.getId()));
        }
    }

    /**
     * 记录金额符号过滤
     *
     * @param cooperationDo 操作记录请求参数
     */
    private void moneySignFilter(CustomerCooperation cooperationDo) {
        if (CustomerConst.CooperationType.REFUND.getId().equals(cooperationDo.getTypeId())) {
            if (cooperationDo.getIncome().compareTo(BigDecimal.ZERO) > 0) {
                cooperationDo.setIncome(cooperationDo.getIncome().negate());
            }
            if (cooperationDo.getPerfor().compareTo(BigDecimal.ZERO) > 0) {
                cooperationDo.setPerfor(cooperationDo.getPerfor().negate());
            }
        } else {
            if (cooperationDo.getIncome().compareTo(BigDecimal.ZERO) < 0) {
                cooperationDo.setIncome(cooperationDo.getIncome().negate());
            }
            if (cooperationDo.getPerfor().compareTo(BigDecimal.ZERO) < 0) {
                cooperationDo.setPerfor(cooperationDo.getPerfor().negate());
            }
        }
    }
}
